JMX接続をひたすらやっていく
こんにちは。齋藤です。
今回のこの記事はJava アドベントカレンダー 2017 4日目に向けた記事です。 今日はJMXと格闘した記録をここに書いておきます。
今回は以下の内容について記述します。
- ローカルのDockerコンテナ上に立ち上げたJVMに対して JMX接続する
- EC2上に立ち上げたJVMに対して JMX接続する
- EC2上のDockerコンテナ上に立ち上げたJVMに対して JMX接続する
今回JMX接続先に利用するのはElasticsearchです。
やっていきます。
ローカルのDockerコンテナ上に立ち上げたJVMに対して JMX接続する
まずは手始めに、簡単なところから攻めていきます。 次のコマンドでElasticsearchを起動します。
docker run -d -it -e "ES_JAVA_OPTS= -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.rmi.port=9010 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010" -p 9010:9010 -p 9200:9200 -p 9300:9300 docker.elastic.co/elasticsearch/elasticsearch:6.0.0
接続してみる
jconsoleの場合はこんな感じ。
jconsole service:jmx:rmi:///jndi/rmi://localhost:9010/jmxrmi
jvisualvmの場合は 画面立ち上がってからJMX接続をUIで追加してください。
jvisualvm
EC2上に立ち上げたJVMに対して JMX接続する
今回はAmazon Linuxを使います。 インスタンスは t2.mediumです。
EC2(Amazon Linux) に Java8 をインストール
デフォルトのJavaは7なので とりあえず、Javaのインストールから始めます。 次のコマンドでだいたい入ります。
sudo yum install java-1.8.0-openjdk-devel.x86_64 -y sudo alternatives --config java
EC2にElasticsearchをインストール
今度はElasticsearchのインストールです。
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0.zip # sha1sum elasticsearch-6.0.0.zip unzip elasticsearch-6.0.0.zip cd elasticsearch-6.0.0/
JMXを有効にしてElasticsearchを起動しておく
ES_JAVA_OPTSにJMXの設定を追加して Elasticsearchを起動しておきます。
ES_JAVA_OPTS="-Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.rmi.port=9010 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=9010" \ elasticsearch-6.0.0/bin/elasticsearch > /dev/null &
socksプロトコルで接続できるようにしておく
ssh -i ~/.ssh/jmx-test.pem -fND 9091 ec2-user@$HOGE_EC2_IP
jconsoleで接続
jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9200 -J-DsocksNonProxyHosts= service:jmx:rmi:///jndi/rmi://localhost:9010/jmxrmi
visualvmで接続
jvisualvm -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9200 -J-DsocksNonProxyHosts=
こっちだと動きませんでした。
jvisualvm -J-Dnetbeans.system_socks_proxy=localhost:9200 -J-Djava.net.useSystemProxies=true
EC2上で動いているDockerコンテナに対してJMX接続
今度はEC2上で Dockerを導入して、Docker コンテナとしてElasticsearchを立ち上げて そのElasticsearchに JMX 接続をしてみましょう。
Docker インストールする
sudo yum install docker -y
Docker のデーモンを立ち上げる
sudo service docker start
sudoなしでdockerコマンドを利用するために、ec2-user を docker グループに追加する
次のコマンドを実行すると、sudoなしでdockerコマンドが利用できる。(セキュリティにご注意ください。)
sudo usermod -a -G docker ec2-user
ログアウトしてログインするか、再起動すると次のようにsudoなしでdocker コマンドが利用できます。
docker ps
Elasticsearchを立ち上げるが、コケる。
docker run -it -e "ES_JAVA_OPTS= -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.rmi.port=9010 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010" -p 9010:9010 -p 9200:9200 -p 9300:9300 docker.elastic.co/elasticsearch/elasticsearch:6.0.0
エラーが発生して落ちました。 次のエラーを見るに、file descriptor と vm.max_map_count が足りないとのこと。
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] [2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
Elasticsearchの起動のために設定を追加していく
ホストOSの設定を編集していきます。
まずは vm.max_map_count。 参考
sudo vim /etc/sysctl.conf # 次の行を追加 vm.max_map_count=262144
次はfile descriptorの設定。これはOSの設定とdocker側の設定をいじります。 ちなみにdocker側の設定を分からず、あたふたしていました。 参考
まずはOS側。
sudo vim /etc/security/limits.conf # 次の行を追加します * soft nofile 1000000 * hard nofile 1000000
今度はdocker側の設定を編集します。 参考
sudo vim /etc/sysconfig/docker # 次の行を追加 # OPTIONS="--default-ulimit nofile=1024:4096" OPTIONS="--default-ulimit nofile=65536:1000000"
再起動したらだいたいいい感じ。
sudo reboot
というわけで、JMXを有効にして Elasticsearchを立ち上げる
設定をいじったおかげで最初実行した時と同じように次のコマンドで立ち上がりました。
docker run -it -e "ES_JAVA_OPTS= -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.rmi.port=9010 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010" -p 9010:9010 -p 9200:9200 -p 9300:9300 docker.elastic.co/elasticsearch/elasticsearch:6.0.0
EC2上のDockerで立ち上がってるElasticsearchに対してJMX接続する
普通にEC2上で立ててる時と変わらない感じでアクセスできました。最高。
jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9200 -J-DsocksNonProxyHosts= service:jmx:rmi:///jndi/rmi://localhost:9010/jmxrmi
jvisualvm -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9200 -J-DsocksNonProxyHosts=
まとめ
色々遠回りした感じはありますが、最終的に、EC2上のDockerコンテナ上のJVMに接続することができました。 普通にリモートのJVMに接続するのとあまり変わりない形になりました。
これは今回の記事にはあまり関係ないのですが visualvmのネットワーク設定画面を開こうとすると めちゃくちゃ重いことが気になりました・・・。